#include "vcd-json-parser.h"
#include "vcd-log.h"
#include "vcd-common.h"
#include "vcd-conf/vcd-conf.h"
#include "vcd-linux-ui/vcd-logined-window.h"
#include "vcd-get-vm-info.h"
#include "vcd-util.h"

static void get_one_vm_info(JsonObject *obj, vm_info* o);
static void get_real_vatual_mac(char *net0, char *real_mac);

void get_one_vm_info(JsonObject *obj, vm_info* o)
{
    const gchar *s = NULL;
    if (json_object_has_member(obj, "vmid"))
        o->vmid = json_object_get_int_member(obj, "vmid");

    if (json_object_has_member(obj, "template"))
        o->Template = json_object_get_int_member(obj, "template");

    if (json_object_has_member(obj, "node")) {
        const gchar* s = json_object_get_string_member(obj, "node");
        if (s)
            strncpy(o->node, s, sizeof(o->node));
    }

    if (json_object_has_member(obj, "status")) {
        s = json_object_get_string_member(obj, "status");
        if (s)
            strncpy(o->status, s, sizeof(o->status));
    }

    if (json_object_has_member(obj, "name")) {
        s = json_object_get_string_member(obj, "name");
        if (s)
            strncpy(o->name, s, sizeof(o->name));
    }

    if (json_object_has_member(obj, "type")) {
        s = json_object_get_string_member(obj, "type");
        if (s)
            strncpy(o->type, s, sizeof(o->type));
    }
}

/*

{
    "data": [{
        "name": "windows.desktop",
        "uptime": 0,
        "template": 0,
        "netout": 0,
        "maxdisk": 42949672960,
        "type": "qemu",
        "diskwrite": 0,
        "node": "n207",
        "disk": 0,
        "diskread": 0,
        "id": "qemu/100",
        "vmid": 100,
        "status": "stopped",
        "cpu": 0,
        "mem": 0,
        "maxmem": 4294967296,
        "maxcpu": 4,
        "netin": 0
    },
    {...},
    {...}
    ]
}

*/
int json_parser_get_vm_info(char *memory, vm_info** pp_info, int *count, char *err_msg)
{
    JsonArray *arr = NULL;
    JsonObject *obj_info = NULL;
    int cnt = 0;
    int i = 0;
    vm_info* info = NULL;
    strcpy(err_msg, "获取虚拟机信息失败");

    JsonParser *parser_info = json_parser_new();
    gboolean bres = json_parser_load_from_data(parser_info, memory, -1, NULL);
    if (!bres) {
        LOG_ERROR("json_parser_load_from_data fail, data:%s", memory);
        return 0;
    }

    JsonNode *node_info  = json_parser_get_root(parser_info);//得到节点
    if (!node_info) {
        LOG_ERROR("json_parser_get_root fail");
        goto fail;
    }

    obj_info = json_node_get_object(node_info);//得到节点内的对象
    if (!obj_info) {
        LOG_ERROR("json_node_get_object fail");
        goto fail;
    }

    if (json_object_has_member(obj_info, "data")) {
        arr = json_object_get_array_member(obj_info, "data");//data对应的数组, array是全局变量，方便多处使用
    } else {
        if (json_object_has_member(obj_info, "code") && json_object_has_member(obj_info, "message")) {
            memset(err_msg, 0, 1024);
            sprintf(err_msg, "code=%ld, %s", json_object_get_int_member(obj_info, "code"),
                                         json_object_get_string_member(obj_info, "message"));
        }
        goto fail;
    }
    
    cnt = json_array_get_length(arr);//得到array内虚机数量，但是后期显示的时候还会排出有些虚机
    info = (vm_info*)g_malloc0(cnt * sizeof(vm_info));
    if (info == NULL)
        goto fail;

    for (i = 0; i < cnt; ++i) {
        JsonObject *obj = json_array_get_object_element(arr, i);
        vm_info* o = info + i;
        get_one_vm_info(obj, o);
    }

    *pp_info = info;
    *count = cnt;
    g_object_unref(parser_info);
    return 0;

fail:
    g_object_unref(parser_info);
    if(info) {
        g_free(info);
        info = NULL;
    }
    return -1;
}

/*
curl -k https://192.168.211.8/API/workspace/terminal/register -H "Authorization: PVEAPIToken=wsagent@pve\!IDV=f43998ab-1135-4e13-8774-e0f78bd2180f" -d '{"clinet_version":"0.37.990-3a60", "machine_id":"4ef19290-698f-4633-b2c5-b6ba338ce1c1", "pve_version":"6.4-3", "name":"v-7tzdd38i", "full_token":"wsagent@pve!IDV", "token":"f43998ab-1135-4e13-8774-e0f78bd2180f", "mip":"192.168.112.233"}' -H "Content-Type: application/json; charset=utf-8" | jq
{
  "code": 1,
  "data": [
    {
      "username": "t-test",
      "password": "pPV8T8F9kgufE"
    },
    {
      "username": "idvtest",
      "password": "dvDKyXMKQqoY2"
    },
    {
      "username": "idvtest01",
      "password": "8RoqGKTJEmxKqCjIq"
    }
  ],
  "message": "OK"
}
*/
int json_parser_heartbeat_record_user_pass_config(char *memory, int *count, char *err_msg) {

    JsonArray *arr = NULL;
    JsonObject *obj_info = NULL;
    LocalmodeUserPass *user_pass = NULL;
    const gchar *str = NULL;
    int cnt = 0;
    int i = 0;
    strcpy(err_msg, "本地模式返回解析失败");
    JsonParser *parser_info = json_parser_new();
    gboolean bres = json_parser_load_from_data(parser_info, memory, -1, NULL);
    if (!bres) {
        LOG_ERROR("json_parser_load_from_data fail, data:%s", memory);
        return 0;
    }

    JsonNode *node_info  = json_parser_get_root(parser_info);//得到节点
    if (!node_info) {
        LOG_ERROR("json_parser_get_root fail");
        goto fail;
    }

    obj_info = json_node_get_object(node_info);//得到节点内的对象
    if (!obj_info) {
        LOG_ERROR("json_node_get_object fail");
        goto fail;
    }

    if (json_object_has_member(obj_info, "data")) {
        arr = json_object_get_array_member(obj_info, "data");
    } else {
        if (json_object_has_member(obj_info, "code") && json_object_has_member(obj_info, "message")) {
            memset(err_msg, 0, 1024);
            sprintf(err_msg, "code=%ld, %s", json_object_get_int_member(obj_info, "code"),
                                         json_object_get_string_member(obj_info, "message"));
        }

        goto fail;
    }

    cnt = json_array_get_length(arr);
    M_DEBUG("localmode user-pass count = %d", cnt);

    if (cnt > 0)
    {
        user_pass = (LocalmodeUserPass*)g_malloc0(cnt * sizeof(LocalmodeUserPass));
        if (user_pass == NULL) {
            goto fail;
        }

        for (i = 0; i < cnt; ++i) {
           JsonObject *obj = json_array_get_object_element(arr, i);
           LocalmodeUserPass* one = user_pass + i;
           str = json_object_get_string_member(obj, "username");
           if (str)
               strncpy(one->username, str, sizeof(one->username));
           str = json_object_get_string_member(obj, "password");
           if (str)
               strncpy(one->password, str, sizeof(one->password));
        }
    }
    heartbeat_record_user_pass_config(user_pass, cnt);

fail:
    g_object_unref(parser_info);
    return -1;
}

/*

{
    "data": {
        "name": "windows.desktop",
        "ide2": "none,media=cdrom",
        "args": "-realtime mlock=off -spice password=123,port=62100,addr=0.0.0.0,seamless-migration=on,streaming-video=filter,image-compression=glz,playback-compression=off,video-codecs=gstreamer:h264 -device intel-hda,id=sound0,bus=pci.0,addr=0xf -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -D /var/log/spice-100.log",
        "smbios1": "uuid=985ed481-3950-4b5f-9290-6229848afacf",
        "ide0": "local-lvm:vm-100-disk-1,size=40G",
        "ide1": "local-lvm:vm-100-disk-2,size=50G",
        "sockets": 1,
        "memory": 4096,
        "cores": 4,
        "net0": "virtio=06:13:FF:8E:FD:62,bridge=vmbr0",
        "digest": "158b1cc64ce8c574f3e6ec4b4231880587c5ab91",
        "ostype": "win10",
        "agent": "1",
        "scsihw": "virtio-scsi-pci",
        "bootdisk": "ide0",
        "net1": "e1000=F6:8E:8D:63:95:DC,bridge=vmbr0",
        "vga": "qxl",
        "numa": 0
    }
}

*/

int json_parser_get_spice_config(char *memory, vm_config_response* resp)
{    
    gboolean bres = FALSE;
    JsonNode *node1  = NULL;
    JsonObject * obj1 = NULL;
    JsonObject *obj2  = NULL;
    JsonParser *parser = json_parser_new();
    if (parser == NULL)
        return -1;

    bres = json_parser_load_from_data(parser, memory, -1, NULL);
    if (bres == FALSE) 
        goto fail;

    node1  = json_parser_get_root(parser);//得到节点
    if (node1 == NULL)
        goto fail;

    obj1 = json_node_get_object(node1);//得到节点内的对象
    if (obj1 == NULL)
        goto fail;

    if (!json_object_has_member(obj1, "data"))
        goto fail;

    obj2 = json_object_get_object_member(obj1, "data");//得到obj1对象data内嵌套的对象
    if (obj2 == NULL)
        goto fail;

    if (json_object_has_member(obj2, "ostype"))
        resp->ostype = strdup(json_object_get_string_member(obj2, "ostype"));

    if (json_object_has_member(obj2, "net0"))
        resp->net0 = strdup(json_object_get_string_member(obj2, "net0"));

    if (json_object_has_member(obj2, "args"))
        resp->args = strdup(json_object_get_string_member(obj2, "args"));

    g_object_unref(parser);
    parser = NULL;

    return 0;

fail:
    g_object_unref(parser);
    return -1;
}

/*

{
    "success": 1,
    "data": [{
        "exists": 1,
        "priority": 3,
        "families": ["inet"],
        "method": "manual",
        "active": 1,
        "type": "eth",
        "iface": "eth0",
        "method6": "manual"
    }, {
        "priority": 4,
        "families": ["inet"],
        "bridge_ports": "eth0",
        "bridge_fd": "0",
        "netmask": "255.255.255.0",
        "method": "dhcp",
        "autostart": 1,
        "type": "bridge",
        "gateway": "192.168.10.1",
        "active": 1,
        "method6": "manual",
        "bridge_stp": "off",
        "address": "192.168.10.221",
        "iface": "vmbr0"
    }]
}

//add by gt
{
	"success": 1,
	"data": [{
		"type": "eth",
		"method": "manual",
		"method6": "manual",
		"iface": "eno1",
		"active": 1,
		"families": ["inet"],
		"priority": 3,
		"exists": 1
	}, {
		"iface": "eno2",
		"exists": 1,
		"priority": 5,
		"method": "manual",
		"method6": "manual",
		"type": "eth",
		"families": ["inet"]
	}, {
		"families": ["inet"],
		"type": "eth",
		"exists": 1,
		"method": "manual",
		"method6": "manual",
		"priority": 7,
		"iface": "eno4"
	}, {
		"families": ["inet"],
		"iface": "eno3",
		"type": "eth",
		"method6": "manual",
		"priority": 6,
		"exists": 1,
		"method": "manual"
	}, {
		"type": "eth",
		"exists": 1,
		"priority": 11,
		"method": "manual",
		"method6": "manual",
		"iface": "enp6s0f3",
		"families": ["inet"]
	}, {
		"bridge_fd": "0",
		"priority": 4,
		"autostart": 1,
		"active": 1,
		"bridge_ports": "eno1",
		"netmask": "255.255.255.0",
		"families": ["inet"],
		"type": "bridge",
		"method": "static",
		"method6": "manual",
		"iface": "vmbr0",
		"bridge_stp": "off",
		"gateway": "192.168.107.1",
		"address": "192.168.107.187"
	}, {
		"families": ["inet"],
		"iface": "enp6s0f2",
		"exists": 1,
		"method6": "manual",
		"method": "manual",
		"priority": 10,
		"type": "eth"
	}, {
		"families": ["inet"],
		"exists": 1,
		"priority": 8,
		"method": "manual",
		"method6": "manual",
		"type": "eth",
		"iface": "enp6s0f0"
	}, {
		"iface": "enp6s0f1",
		"type": "eth",
		"method6": "manual",
		"priority": 9,
		"exists": 1,
		"method": "manual",
		"families": ["inet"]
	}]
}
*/
//ppp_ip二维数组存储所有合适的ip
gboolean json_parser_get_server_ip(char *memory, char ***ppp_ip, int* count)
{
    JsonArray* add_array = NULL;
    int add_count = 0;
    int i = 0, j = 0;
    JsonNode *node_info  = NULL;
    JsonObject *obj_info = NULL;
    gboolean bres = FALSE;
    char** pp_ip = NULL;
    const gchar* m = NULL;

    JsonParser *parser_info = json_parser_new();
    if(parser_info == NULL){
        return FALSE;
    }

    bres = json_parser_load_from_data(parser_info, memory, -1, NULL);
    if(bres != TRUE){
        goto fail;
    }

    node_info  = json_parser_get_root(parser_info);//得到节点
    obj_info = json_node_get_object(node_info);//得到节点内的对象
    if (obj_info == NULL) {
        M_DEBUG("obj_info == NULL");
       goto fail;
    }

    //must success
    if(json_object_has_member(obj_info, "success")){
        gint64 n = json_object_get_int_member(obj_info, "success");
        if(n == 0){
            goto fail;
        }
    }else{
        goto fail;
    }

    //解析data
    if(json_object_has_member(obj_info, "data")){
        add_array = json_object_get_array_member(obj_info, "data");
        if (add_array == NULL) {
            M_DEBUG("add_array == NULL");
            goto fail;
        }
    }else{
        goto fail;
    }

    //get all ipv4
    add_count = json_array_get_length(add_array);
    pp_ip = (char**)malloc(add_count * sizeof(char*));
    M_DEBUG("server_ip array count = %d", add_count);
    for (i = 0, j = 0; i < add_count; i++) {
        JsonObject *add_info = json_array_get_object_element(add_array, i);

        //must active
        if(json_object_has_member(add_info, "active")){
            gint64 n = json_object_get_int_member(add_info, "active");
            if(n == 0){
                M_DEBUG("server_ip array[%d] active = 0", i);
                continue;
            }
        }else{
            M_DEBUG("server_ip array[%d] has no member active", i);
            continue;
        }

        //currently only support ipv4
        // if (json_object_has_member(add_info, "families")) {
        //     JsonArray *fam_array = json_object_get_array_member(add_info, "families");//????families字段里面的是一个数组
        //     m =  json_array_get_string_element(fam_array, 0);//数组的第一个字段是字符串 "inet"
        //     M_DEBUG("server_ip array[%d] families = %s", i, m);
        //     if(strncmp(m, "inet", strlen("inet")) != 0) {
        //         M_DEBUG("server_ip array[%d] families != \"inet\"", i);
        //         continue;
        //     }
        // }

        if (json_object_has_member(add_info, "address")) {
            m = json_object_get_string_member(add_info, "address");
            char** pos = pp_ip + j;
            *pos = strdup(m);
            if(*pos == NULL){
                continue;
            }
            ++j;
        }
    }

    g_object_unref(parser_info);
    *ppp_ip = pp_ip;
    *count = j;
    return TRUE;

fail:
    g_object_unref(parser_info);
    return FALSE;
}


/*

{
    "success": 1,
    "data": {
        "host": "pvespiceproxy:5c908b20:101:n207::527a94e4b1e724c1462c791d13b712367aef2cff",
        "title": "VM 101 - desk-x64-101",
        "tls-port": 61000,
        "toggle-fullscreen": "Shift+F11",
        "type": "spice",
        "proxy": "http://192.168.10.221:3128",
        "password": "21e771ffc0bc322d8ed261106b763e4545d91d4f",
        "release-cursor": "Ctrl+Alt+R",
        "secure-attention": "Ctrl+Alt+Ins",
        "delete-this-file": 1,
        "ca": "-----BEGIN CERTIFICATE-----\\nMIIFwjCCA6qgAwIBAgIJAMt+klAuOBaoMA0GCSqGSIb3DQEBCwUAMHYxJDAiBgNV\\nBAMMG1Byb3htb3ggVmlydHVhbCBFbnZpcm9ubWVudDEtMCsGA1UECwwkMWM0MTgw\\nOTItMzc1NS00OTVjLWI1ZWYtNjU4MjA2MTFiOTU1MR8wHQYDVQQKDBZQVkUgQ2x1\\nc3RlciBNYW5hZ2VyIENBMB4XDTE4MTAzMDA3MzM0OFoXDTI4MTAyNzA3MzM0OFow\\ndjEkMCIGA1UEAwwbUHJveG1veCBWaXJ0dWFsIEVudmlyb25tZW50MS0wKwYDVQQL\\nDCQxYzQxODA5Mi0zNzU1LTQ5NWMtYjVlZi02NTgyMDYxMWI5NTUxHzAdBgNVBAoM\\nFlBWRSBDbHVzdGVyIE1hbmFnZXIgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\\nggIKAoICAQDc3O6Jf1/FSEnskXiU3QwH22PQsM10ol4cMqO0f4204l8qIXlU/V6n\\n+NXV2JDxYKhsSfldv72HnhQB+qnt46sQHsqZ5vfAqwQkfYzNkp8wueVACL3RymDD\\nw9C2yE228TCICZw8GYHlYLVKrl2/STZCkFOLvmVK+bLvC8igIFipqErxsFpJVQVm\\n1n0VPlp2/3JadHN0o6pDNXtMoijcX0Iouz4+u5NWoppkD1FV6kYTXNlF8RQdPNbZ\\n8Yp2VI8Y3+4IMAiWs41IREvrjq76ZCf+X7a6FWGZeysFw1PERkAQ2a9L0d2lWy0a\\nCH1TmYF7Xkmt/2+hL+aQc8IJYnJ6nWk25ozF6I8go0uEDsExitAFVNI//9zDilKb\\nnnfasWiDvd6xVkL0dk2911cAMxQgRi6RnSOJzofUWUCRn633SiniMODbd+jwdccA\\nqbhN2Q7N8O+9z6NqSLrlLKnStH2Q5OmKbvvh0TS/V1NKEawHOveEDfYaXsbbZ9l+\\nwCvV4TfjwCow1O8h9MLCzH5z52w0yps7RbfQIQnNhWQdLBzcPPfJmzL0Up85jJlr\\nNf0r4kpBknV6lJMo/wIvp6nfIN+xC1WnM+oNpmksSF+zdLewy3QPkmR3nF+MQn6p\\n8OeGCUDx/ZV3Z058x+Ydn4wZ6U2zq/A0ST8v+EoMWgoK9ScnwEGWsQIDAQABo1Mw\\nUTAdBgNVHQ4EFgQUNaQsqDVZ+d1NzmOGPBCDKhlhzYQwHwYDVR0jBBgwFoAUNaQs\\nqDVZ+d1NzmOGPBCDKhlhzYQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF\\nAAOCAgEAtUsTHQAEBrncmneB2HPQ+KdKbVeW4r/i0tiC12XJEQAv5lsIbiw+Kb3u\\nmYhuwx8xoGWTfuDucKHvC6AVl4Ot3nvjzb60SocvTtI2cRhGND1nak51ShHBiuGL\\nL8i+XRfF+7btVCs0gvFxFBvmvJnPB3qZ7plZ4rsgMu6sGQ7SmHIQcXYWIjv4XpV1\\nB/pl3ifRVdppncjXmQLFuPl14HtWZLh7if1nu4cClUDdauaxS5+WNDyxbLnG6Ewq\\nPywTd1fZ7TAdqT8ncMqfFoyUzSE/6svQzzVsuru0xfSyzmvbcWaRsYzneFJiyYVO\\nFIjzyiepkLIpX/5AlGh995zsZvIiBF/jfJ1RvZDkb56X72Dat8er+qGhZR2QG5ND\\nG/oz6l1TPJnu5uZXtvbOZL0e/4dtu+stJxE5k4qZ+XnQFLNirX7jq8nl95WWzolM\\namn8EhgQD0WCVXJlBA4Uv5WT+Aq2lVH1NBuk0QHDcYhpDpd9FHnxyuOvL8dxj2J5\\nqL+JT61UY/F659vdLEQKYOok+td0INw6jBG8dT1jbuvORLW2nQ5I6WL5+doT1COV\\nhjw3v+yigNFUBxSrzZno+mTxqiu2v4vEyLZnqB3wkV6CXfQ/83aWLGMWZaF7eequ\\nWWKFr1cfQwualuyyDwvt7k2EnKMcVAPjBlKCwT5rDkhpa7+vreI=\\n-----END CERTIFICATE-----\\n",
        "host-subject": "OU=PVE Cluster Node,O=Proxmox Virtual Environment,CN=n207.verycloud.cn"
    }
}

{
    "data": null,
    "message": "VM 108 not running\n",
    "success": 0,
    "status": 500
}

*/
int json_parser_get_spice_proxy(char *memory, spice_proxy_data* d)
{	
    JsonObject *obj1 = NULL;
    JsonObject *obj2 = NULL;
    gboolean bres = TRUE;
    JsonNode *node1 = NULL;
    JsonParser *parser = json_parser_new();

    if (parser == NULL)
        return -1;

    bres = json_parser_load_from_data(parser, memory, -1, NULL);
    if (bres != TRUE)
        goto fail;

    node1 = json_parser_get_root(parser);//得到节点
    if (node1 == NULL)     
        goto fail;

    obj1 = json_node_get_object(node1);//得到节点内的对象
    if (obj1 == NULL)
        goto fail;

    if (!json_object_has_member(obj1, "success"))
        goto fail;

    d->success = json_object_get_int_member(obj1, "success");

    if (d->success != 1){
        if(json_object_has_member(obj1, "message"))
            d->fail_msg = strdup(json_object_get_string_member(obj1, "message"));
        else
            d->fail_msg = NULL;
    } else {
        obj2 = json_object_get_object_member(obj1, "data");
        d->host = strdup(json_object_get_string_member(obj2, "host"));
        d->title = strdup(json_object_get_string_member(obj2, "title"));
        d->tls_port = json_object_get_int_member(obj2, "tls-port");
        d->type = strdup(json_object_get_string_member(obj2, "type"));
        d->proxy = strdup(json_object_get_string_member(obj2, "proxy"));
        d->password = strdup(json_object_get_string_member(obj2, "password"));
    }

//    obj2 = json_object_get_object_member(obj1, "data");
//    if (1 != json_object_get_int_member(obj1, "success")) {
//        delete_g_connect_label_and_spinner();
//        char strMsg[500] = {0};
//        sprintf(strMsg, "VM %d not running\n", connect_data.vmid);
//        M_DEBUG("%s", strMsg);
//        if (strcmp(strMsg, json_object_get_string_member(obj1, "message")) == 0) {
//            //startSystemBox(&connect_data);
//        }
//        else {
//            M_DEBUG("errorMessage:%s", json_object_get_string_member(obj1, "message"));
//            message_box(json_object_get_string_member(obj1, "message"));
//        }
//        g_object_unref(parser);
//        return NULL;
//    }

    g_object_unref(parser);
    parser = NULL;
    return 0;
fail:
    g_object_unref(parser);
    parser = NULL;
    return -1;
}

/*

{
    "data": {
        "username": "root@pam",
        "CSRFPreventionToken": "5C8F36B0:znYPAd9bW4znXtt9BGL8oVYBKFk",
        "ticket": "PVE:root@pam:5C8F36B0::lzg...",
        "cap": {
            "vms": {
                "VM.Console": 1,
                "VM.Audit": 1,
                "VM.Clone": 1,
                "VM.Migrate": 1,
                "VM.Snapshot": 1,
                "Permissions.Modify": 1,
                "VM.Monitor": 1,
                "VM.Config.Options": 1,
                "VM.Backup": 1,
                "VM.Config.HWType": 1,
                "VM.Config.Network": 1,
                "VM.Config.CDROM": 1,
                "VM.Config.Memory": 1,
                "VM.Config.CPU": 1,
                "VM.Snapshot.Rollback": 1,
                "VM.Allocate": 1,
                "VM.PowerMgmt": 1,
                "VM.Config.Disk": 1
            },
            "access": {
                "Group.Allocate": 1,
                "User.Modify": 1,
                "Permissions.Modify": 1
            },
            "storage": {
                "Datastore.Audit": 1,
                "Permissions.Modify": 1,
                "Datastore.Allocate": 1,
                "Datastore.AllocateTemplate": 1,
                "Datastore.AllocateSpace": 1
            },
            "dc": {
                "Sys.Audit": 1
            },
            "nodes": {
                "Sys.Modify": 1,
                "Sys.PowerMgmt": 1,
                "Sys.Console": 1,
                "Permissions.Modify": 1,
                "Sys.Audit": 1,
                "Sys.Syslog": 1
            }
        }
    }
}

*/

int json_parser_get_ticket(char *memory, ticket_param *p)
{
    JsonNode *node1 = NULL;
    gboolean bres = TRUE;
    GError *error = NULL;
    JsonObject *obj1  = NULL;
    JsonObject *obj2 = NULL;
    JsonParser *parser = json_parser_new();
    if(parser == NULL){
        M_DEBUG("json_parser_new fail:%m");
        return -1;
    }

    bres = json_parser_load_from_data(parser, memory, -1, &error);
    if(!bres){
        M_DEBUG("json_parser_load_from_data fail, data:%s error:%s", memory, error->message);
        goto fail;
    }

    node1 = json_parser_get_root(parser);//得到节点
    if(node1 == NULL){
        goto fail;
    }

    obj1 = json_node_get_object(node1);//得到节点内的对象
    if(obj1 == NULL){
        goto fail;
    }

    if(json_object_has_member(obj1,"data")){
        obj2 = json_object_get_object_member(obj1, "data");//得到obj1对象data内嵌套的对象
        if(obj2 == NULL){
            goto fail;
        }
    }else{
        goto fail;
    }

    if(json_object_has_member(obj2,"CSRFPreventionToken")){
        p->token = g_strdup(json_object_get_string_member(obj2, "CSRFPreventionToken"));
        if(p->token == NULL){
            goto fail;
        }
    }else{
        goto fail;
    }

    if(json_object_has_member(obj2,"ticket")){
        p->ticket = g_strdup(json_object_get_string_member(obj2, "ticket"));
        if(p->ticket == NULL){
            goto fail;
        }
    }else{
        goto fail;
    }

    return 0;
fail:
    g_object_unref(parser);
    parser = NULL;
    if(error){
        g_error_free(error);
        error = NULL;
    }
    G_SAFE_FREE(p->token);
    G_SAFE_FREE(p->ticket);
    return -1;
}

// api:https://192.168.112.4:8006/api2/json/nodes/ce/qemu/131/config
// {
// 	"data": {
// 		"vga": "qxl",
// 		"name": "7x64SD",
// 		"virtio1": "local-lvm:vm-131-disk-1,size=32G",
// 		"boot": "dcn",
// 		"smbios1": "uuid=c2f20229-19aa-4d44-848b-36aa5adabe20",
// 		"net0": "virtio=4A:DD:58:A8:EE:92,bridge=vmbr0",
// 		"virtio0": "local-lvm:vm-131-disk-0,size=32G",
// 		"scsihw": "virtio-scsi-pci",
// 		"memory": 4096,
// 		"digest": "7157c0efde8cf4d9d03edaaa0333b6b6c666d0ce",
// 		"agent": "1",
// 		"cores": 4,
// 		"numa": 0,
// 		"bootdisk": "virtio0",
// 		"ostype": "win7",
// 		"args": "-device intel-hda,id=sound0,bus=pci.0,addr=0xf -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0",
// 		"sockets": 1
// 	}
// }
int json_parser_get_rdp_guest_system_type(char *memory, char *sys_type)
{
    g_return_val_if_fail(memory != NULL, -1);

    JsonNode *node = NULL;
    JsonObject *obj1  = NULL;
    JsonObject *obj2 = NULL;
    gboolean bres = FALSE;
    GError *error = NULL;
    JsonParser *parser = json_parser_new();

    if(parser == NULL){
        return -1;
    }

    bres = json_parser_load_from_data(parser, memory, -1, &error);
    if(bres != TRUE){        
        goto fail;
    }
    
    node  = json_parser_get_root(parser);//得到节点
    if(node == NULL){
        goto fail;
    }

    obj1 = json_node_get_object(node);//得到节点内的对象
    if(obj1 == NULL){
        goto fail;
    }

    if (!json_object_has_member(obj1, "data"))
        goto fail;

    obj2 = json_object_get_object_member(obj1, "data");//得到obj1对象data内嵌套的对象
    if (!obj2) {
       goto fail;
    }

    if (json_object_has_member(obj2, "ostype")) {
        strcpy(sys_type, json_object_get_string_member(obj2, "ostype"));
    }

    g_object_unref(parser);
    parser = NULL;
    return 0;
fail:    
    g_object_unref(parser);
    parser = NULL;
    if(error){
        g_error_free(error);
        error = NULL;
    }
    return -1;
}

static
void get_real_vatual_mac(char *net0, char *real_mac)
{
    g_return_if_fail(net0 != NULL); 
    
    //M_DEBUG("net0 = %s", net0);
    
    char *tmp1 = strstr(net0, "=");
    if(!tmp1) return;

    tmp1++;
    
    char *tmp2 = strstr(tmp1, ",");
    if(!tmp2) return;

    int len = tmp2 - tmp1;

    for (int i = 0; i < len; i++) {
        tmp1[i] = tolower(tmp1[i]);
    }
    strncpy(real_mac, tmp1,len);
}

// {
// 	"data": {
// 		"result": [{
// 			"ip-addresses": [{
// 				"ip-address": "fe80::4d09:f4c6:59f7:324f%11",
// 				"ip-address-type": "ipv6",
// 				"prefix": 64
// 			}, {
// 				"ip-address-type": "ipv4",
// 				"prefix": 24,
// 				"ip-address": "192.168.118.253"
// 			}],
// 			"name": "����ute",
// 			"hardware-address": "82:93:b0:00:55:bf"
// 		}, {
// 			"name": "Loopback Pseudo-Interface 1",
// 			"ip-addresses": [{
// 				"prefix": 128,
// 				"ip-address-type": "ipv6",
// 				"ip-address": "::1"
// 			}, {
// 				"prefix": 8,
// 				"ip-address-type": "ipv4",
// 				"ip-address": "127.0.0.1"
// 			}]
// 		}, {
// 			"ip-addresses": [{
// 				"prefix": 128,
// 				"ip-address-type": "ipv6",
// 				"ip-address": "fe80::5efe:192.168.118.253%12"
// 			}],
// 			"name": "isatap.{46C04358-3A6A-4531-A504-8517862FB133}",
// 			"hardware-address": "00:00:00:00:00:00"
// 		}]
// 	}
// }
gboolean json_parser_get_rdp_guest_ip(char *memory, char *ip)
{    
   return json_parser_get_rdp_guest_ip_with_net0(memory,ip,connect_data.net0);
}

gboolean json_parser_get_rdp_guest_ip_with_net0(char *memory, char *ip,char* net0){
    JsonNode *node = NULL;
    JsonObject *obj = NULL;
    gboolean bres = FALSE;
    JsonObject *obj_info= NULL;
    JsonArray *guest_array = NULL;
    char real_mac[30] = {0};
    int i = 0;
    int num = 0;

    g_return_val_if_fail(memory != NULL, FALSE); 
    JsonParser* parser = json_parser_new();
    g_return_val_if_fail(parser != NULL, -1);

    bres = json_parser_load_from_data(parser, memory, -1, NULL);
    if(bres != TRUE){
        goto fail;
    }

    node = json_parser_get_root(parser);//得到节点
    if(node == NULL){
        goto fail;
    }

    obj = json_node_get_object(node);//得到节点内的对象
    if(obj == NULL){
        goto fail;
    }

    if (!json_object_has_member(obj, "data")) 
        goto fail;
    
    obj_info = json_object_get_object_member(obj, "data");
    if(obj_info == NULL){
        goto fail;
    }

    guest_array = json_object_get_array_member(obj_info, "result");
    if(!guest_array)
        goto fail;

    num = json_array_get_length(guest_array);

    get_real_vatual_mac(net0, real_mac);

    for (i = 0; i < num; i++) {
        JsonObject *obj_of_array = json_array_get_object_element(guest_array, i);
        if (json_object_has_member(obj_of_array, "hardware-address")) {

            if (strcmp(real_mac, json_object_get_string_member(obj_of_array, "hardware-address")) == 0) {

                JsonArray *ip_array = json_object_get_array_member(obj_of_array, "ip-addresses");

                for (int j = 0; j < json_array_get_length(ip_array); j++) {

                    JsonObject *obj_ip = json_array_get_object_element(ip_array, j);

                    if (strcmp("ipv4", json_object_get_string_member(obj_ip, "ip-address-type")) == 0) {

                        strcpy(ip, json_object_get_string_member(obj_ip, "ip-address"));
                        g_object_unref(parser);
                        return 0;
                    }
                }
            }
        }
    }
    g_object_unref(parser);
    return -1;
fail:
    g_object_unref(parser);
    return -1;
}

int parse_connecting_num(char* memory, int* pre_link)
{
    JsonNode *node_info  =NULL;
    JsonObject *obj_info = NULL;
    g_return_val_if_fail(memory != NULL, -1);

    JsonParser *parser_info = json_parser_new();
    if(parser_info == NULL)
        return -1;

    json_parser_load_from_data(parser_info, memory, -1, NULL);

    node_info  = json_parser_get_root(parser_info);//得到节点
    if (node_info == NULL)
        goto fail;

    obj_info = json_node_get_object(node_info);//得到节点内的对象
    if (obj_info == NULL)
        goto fail;

    *pre_link = json_object_get_int_member(obj_info, "preLink");

    g_object_unref(parser_info);

    return 0;

fail:
    g_object_unref(parser_info);
    return -1;
}


int parse_client_disconnect(char *memory, disconnect_res* s)
{
    gboolean bres = FALSE;
    JsonNode *node_info  = NULL;
    JsonObject *obj_info = NULL;
    JsonParser *parser_info = json_parser_new();
    if (parser_info == NULL) {
        LOG_ERROR("json_parser_new error");
        return -1;
    }

    bres = json_parser_load_from_data(parser_info, memory, -1, NULL);
    if (bres != TRUE) {
        LOG_ERROR("json_parser_load_from_data error");
        goto fail;
    }

    node_info  = json_parser_get_root(parser_info);//得到节点
    if (node_info == NULL) {
        LOG_ERROR("json_parser_get_root error");
        goto fail;
    }

    obj_info = json_node_get_object(node_info);//得到节点内的对象
    if (obj_info == NULL) {
        LOG_ERROR("json_node_get_object error");
        goto fail;
    }

    s->pre_link = json_object_get_int_member(obj_info, "preLink");
    s->max_connection = json_object_get_int_member(obj_info, "maxNum");
    s->connected_num = json_object_get_int_member(obj_info, "connectedNum");
    M_DEBUG("pre_link:%d\nmax_connection:%d\nconnected_num:%d",
            s->pre_link, s->max_connection, s->connected_num);
    g_object_unref(parser_info);
    return 0;

fail:
    g_object_unref(parser_info);
    return -1;
}
/*
{
    "host": "192.168.32.50",
    "port": "61000",
    "password": "123",
    "protocol": "spice/stream/rdp",
    "stream": "on",
    "streamip": "192.168.199.241",
    "streamport": "3389",
    "windowsUsername":"test",
    "windowsPassword":"123.com",
    "expires_in":1577265621,
    "audio":"on/off",
    "usb":"on/off",
    "local_disk_redirect":"on/off"
    "log":"on/off"   // 此字段还未通知后端开发
    "proxy":"http://vdp.verycloud.cn:3128"
    "gwdata":"xxxxx"
    "vmid": 100
    "vmnode":"str"
    "vmname":"str"
    "username":"str"
    "scale":"100/140/180"
}
*/
gboolean vcd_json_parser_spice_connect_data(const char* json_str, spice_connect_data* scd) {
    g_return_val_if_fail(json_str != NULL, FALSE);
    g_return_val_if_fail(scd != NULL, FALSE);

    //M_DEBUG("json_str:%s", json_str);

    char fail_msg[100] = {0};
    JsonNode *node = NULL;
    JsonObject *obj = NULL;
    JsonParser* parser = json_parser_new();

    g_return_val_if_fail(parser != NULL, FALSE);

    GError *err = NULL;
    if (!json_parser_load_from_data(parser, json_str, -1, &err)) {
        if(err)
            sprintf(fail_msg, "%s", err->message);
        goto fail;
    }

    node = json_parser_get_root(parser);//得到节点
    if (node == NULL) {
        sprintf(fail_msg, "json_parser_get_root err json:%s", json_str);
        goto fail;
    }

    obj = json_node_get_object(node);//得到节点内的对象
    if (obj == NULL) {
        sprintf(fail_msg, "json_node_get_object err json:%s", json_str);
        goto fail;
    }

    if (!json_object_has_member(obj, "vmid")) {
        sprintf(fail_msg, "vclient未解析到vmid参数");
        goto fail;
    }
    if (!json_object_has_member(obj, "node")) {
        sprintf(fail_msg, "vclient未解析到node参数");
        goto fail;
    }

    scd->vmid = json_object_get_int_member(obj, "vmid");

    const char *str = json_object_get_string_member(obj, "node");
    if (str)
        sprintf(scd->vmnode, "%s", str);

    if (json_object_has_member(obj, "name")) {
        str = json_object_get_string_member(obj, "name");
        if (str)
            sprintf(scd->vmname, "%s", str);
    }

    if (json_object_has_member(obj, "username")) {
        str = json_object_get_string_member(obj, "username");
        if (str)
            sprintf(scd->username, "%s", str);
    }

    if (json_object_has_member(obj, "instance_id")) {
        str = json_object_get_string_member(obj, "instance_id");
        if (str)
            sprintf(scd->instance_id, "%s", str);
    }

    if (json_object_has_member(obj, "protocol")) {
        str = json_object_get_string_member(obj, "protocol");
        if (str)
            sprintf(scd->protocol, "%s", str);

        scd->protocol_type = PROTOCOL_UNKNOW;
        if (str && (strcmp(str, "spice") == 0)){
            scd->protocol_type = PROTOCOL_SPICE;
            scd->use_rdp = FALSE;
        }
        else if(str && (strcmp(str, "rdp") == 0)){
            scd->protocol_type = PROTOCOL_RDP;
            scd->use_rdp = TRUE;
        }
        else if(str && (strcmp(str, "stream") == 0)){
            scd->protocol_type = PROTOCOL_STREAM;
            scd->use_rdp = TRUE;
        }
    }

    //默认6300
    sprintf(scd->api_port, "6300");
    if (json_object_has_member(obj, "api_port")) {
        str = json_object_get_string_member(obj, "api_port");
        if (str)
            sprintf(scd->api_port, "%s", str);
    }

    //默认100
    if (json_object_has_member(obj, "scale")) {
        str = json_object_get_string_member(obj, "scale");
        if (str)
          scd->extra_scale = strdup(str);
    }

    // get spice args
    const char* host_key     = "host";
    const char* port_key     = "port";
    const char* password_key = "password";
    const char* proxy_key = "proxy";

    if (!json_object_has_member(obj, host_key)) {
        sprintf(fail_msg, "vclient未解析到spice host参数");
        goto fail;
    }
    if (!json_object_has_member(obj, port_key)) {
        sprintf(fail_msg, "vclient未解析到spice port参数");
        goto fail;
    }
    if (!json_object_has_member(obj, password_key)) {
        sprintf(fail_msg, "vclient未解析到spice password参数");
        goto fail;
    }

    str = json_object_get_string_member(obj, host_key);
    sprintf(scd->host, "%s", str);

    str = json_object_get_string_member(obj, port_key);
    sprintf(scd->port, "%s", str);

    str = json_object_get_string_member(obj, password_key);
    sprintf(scd->password, "%s", str);

    if (json_object_has_member(obj, proxy_key)) {
        str = json_object_get_string_member(obj, proxy_key);
        sprintf(scd->proxy, "%s", str);
    }

    // get rdp args
    sprintf(scd->rdp_port, "%s", "3389");
    const char* streamer_key = "stream";
    const char* streamer_host_key = "streamip";
    const char* streamer_port_key = "streamport";
    const char* streamer_extend_key = "streamExtend";

    if (json_object_has_member(obj, streamer_key)
            && json_object_has_member(obj, streamer_host_key)
            && json_object_has_member(obj, streamer_port_key)) {

        str = json_object_get_string_member(obj, streamer_host_key);
        if (str)
            sprintf(scd->rdp_host, "%s", str);

        str = json_object_get_string_member(obj, streamer_port_key);
        if (str)
            sprintf(scd->rdp_port, "%s", str);

        str = json_object_get_string_member(obj, streamer_key);
        if (strstr(str, "on"))
            scd->use_rdp = TRUE;
    }

    if (json_object_has_member(obj, streamer_extend_key)) {
        str = json_object_get_string_member(obj, streamer_extend_key);
        if (str)
            scd->streamExtend = strdup(str);
    }

    const char* windows_username_key = "windowsUsername";
    const char* windows_password_key = "windowsPassword";

    if (json_object_has_member(obj, windows_username_key)
            && json_object_has_member(obj, windows_password_key)) {

        str = json_object_get_string_member(obj, windows_username_key);
        if (str)
            sprintf(scd->guest_name, "%s", str);

        str = json_object_get_string_member(obj, windows_password_key);
        if (str)
            sprintf(scd->guest_pass, "%s", str);

        scd->use_guest_user_pass = TRUE;
    }

    // expires_in
    const char* expires_in_key = "expires_in";
    if (json_object_has_member(obj, expires_in_key))
        scd->expires_in = json_object_get_int_member(obj, expires_in_key);

    // audio:on/off
    const char* audio_key = "audio";
    if (json_object_has_member(obj, audio_key)) {
        str = json_object_get_string_member(obj, audio_key);
        if (str && (strcmp(str, "on") == 0))
            scd->use_audio = TRUE;
    }

    // usb:on/off
    const char* usb_key = "usb";
    if (json_object_has_member(obj, usb_key)) {
        str = json_object_get_string_member(obj, usb_key);
        if (str && (strcmp(str, "on") == 0))
            scd->use_usb_redir = TRUE;
    }

    // local_disk_redirect:on/off
    const char* local_disk_redirect_key = "local_disk_redirect";
    if (json_object_has_member(obj, local_disk_redirect_key)) {
        str = json_object_get_string_member(obj, local_disk_redirect_key);
        if (str && (strcmp(str, "on") == 0))
            scd->use_local_disk_redirect = TRUE;
    }

    // gdi:1/0
    const char* gdi = "gdi";
    if (json_object_has_member(obj, gdi)) {
        str = json_object_get_string_member(obj, gdi);
        if (str && (strcmp(str, "1") == 0))
            scd->gdi = TRUE;
    }

    // log:on/off
    const char* log_key = "log";
    if (json_object_has_member(obj,log_key)) {
        str = json_object_get_string_member(obj, log_key);
        if (str && (strcmp(str, "off") == 0)) {
            //scd->use_log = TRUE;
            M_DEBUG("use log = off");
            vcd_log_open_ctl = FALSE;
        }
    }

    const char* gw_key = "gwdata";
    if (json_object_has_member(obj, gw_key)) {
        str = json_object_get_string_member(obj, gw_key);
        if (str)
          scd->gw = strdup(str);
    }

    const char* quality_key = "image_quality";
    if (json_object_has_member(obj, quality_key)) {
        str = json_object_get_string_member(obj, quality_key);
        if(str)
            scd->image_quality = atoi(str);
    }
    const char* rate = "rate";
    if (json_object_has_member(obj, rate)) {
        str = json_object_get_string_member(obj, rate);
        if(str)
            scd->image_quality = atoi(str);
    }
    g_object_unref(parser);
    return TRUE;
fail:
    sprintf(scd->fail_msg, "%s", fail_msg);
    g_object_unref(parser);
    return FALSE;
}

/*
 *   curl 'https://{host}/api/user/login' --data 'username=xxxx&password=xxxx'
 *
      {
        "code": 1,
        "message": "\u64cd\u4f5c\u5b8c\u6210",
        "uid": "feng",
        "role": ["PVEVMUser"],

        "ticket": "",
        "CSRFPreventionToken": "",
        "PHPSESSID": "",
        "token": ""
      }
*/
gboolean vcd_json_parser_api_user_login(const char* json_str, vcd_api_login_data* vald) {
    g_return_val_if_fail(json_str != NULL, FALSE);
    g_return_val_if_fail(vald != NULL, FALSE);

    M_DEBUG("json_str:%s", json_str);

    char fail_msg[100] = {0};
    sprintf(fail_msg, "%s", "登录失败！");
    JsonNode *node = NULL;
    JsonObject *obj = NULL;
    JsonObject *user_obj = NULL;

    JsonGenerator *build_g = NULL;
    JsonNode *build_root = NULL;

    JsonParser* parser = json_parser_new();

    g_return_val_if_fail(parser != NULL, FALSE);

    GError *err = NULL;
    if (!json_parser_load_from_data(parser, json_str, -1, &err)) {
        if(err) {
            sprintf(fail_msg, "not json, try old api");
        }
        goto fail;
    }

    node = json_parser_get_root(parser);//得到节点
    if (node == NULL) {
        sprintf(fail_msg, "数据解析失败:%s", json_str);
        goto fail;
    }

    obj = json_node_get_object(node);//得到节点内的对象
    if (obj == NULL) {
        sprintf(fail_msg,"数据解析失败:%s", json_str);
        goto fail;
    }

    const char* code_key = "code";
    const char* token_key = "token";
    const char* user_key = "user";
    const char* refresh_token_key = "refresh_token";

    if (!json_object_has_member(obj, code_key))
        goto fail;

    vald->code = json_object_get_int_member(obj, code_key);
    if (vald->code == 401) {
        sprintf(fail_msg, "%s", "用户名或密码错误!");
        goto fail;
    }

    if (!json_object_has_member(obj, token_key)) {
        sprintf(fail_msg, "%s", "未获取到token字段!");
        M_DEBUG("未获取到token字段");
        goto fail;
    }

    const char* str = json_object_get_string_member(obj, token_key);
    vald->token = strdup(str);

    if (!json_object_has_member(obj, refresh_token_key)) {
        sprintf(fail_msg, "%s", "未获取到refresh_token字段!");
        M_DEBUG("未获取到refresh_token字段");
        vald->refresh_token = NULL;
    } else {
        const char* re_str = json_object_get_string_member(obj, refresh_token_key);
        vald->refresh_token = strdup(re_str);
    }



    if (!json_object_has_member(obj, user_key)) {
        //sprintf(fail_msg, "%s", "未获取到user字段!");
        M_DEBUG("未获取到user字段");
        //goto fail;
    } else {
        user_obj = json_object_get_object_member(obj, user_key);
        build_g = json_generator_new();
        build_root = json_node_new(JSON_NODE_OBJECT);
        json_node_set_object(build_root, user_obj);
        json_generator_set_root(build_g, build_root);
        vald->user_data = strdup(json_generator_to_data(build_g, NULL));
        M_DEBUG("userdata=%s", vald->user_data);
    }
     g_object_unref(parser);
    return TRUE;
fail:
    vald->fail_msg = strdup(fail_msg);
    g_object_unref(parser);
    return FALSE;
}

gboolean vcd_json_parser_api_vm_vclient(const char* json_str,vcd_api_vclient_data* vvd){
    g_return_val_if_fail(json_str != NULL, FALSE);
    g_return_val_if_fail(vvd != NULL, FALSE);

    M_DEBUG("json_str:%s", json_str);

    char fail_msg[100] = {0};
    JsonNode *node = NULL;
    JsonObject *obj = NULL;

    JsonParser* parser = json_parser_new();

    g_return_val_if_fail(parser != NULL, FALSE);

    GError *err = NULL;
    if (!json_parser_load_from_data(parser, json_str, -1, &err)) {
        if(err) {
            sprintf(fail_msg, "not json, try old api");
        }
        goto fail;
    }

    node = json_parser_get_root(parser);//得到节点
    if (node == NULL) {
        sprintf(fail_msg, "数据解析失败:%s", json_str);
        goto fail;
    }

    obj = json_node_get_object(node);//得到节点内的对象
    if (obj == NULL) {
        sprintf(fail_msg,"数据解析失败:%s", json_str);
        goto fail;
    }

    const char* code_key = "code";
    const char* data_key = "data";

    if (!json_object_has_member(obj, code_key))
        goto fail;

    vvd->code = json_object_get_int_member(obj, code_key);
    if (vvd->code != 1) {
        goto fail;
    }

    if (!json_object_has_member(obj, data_key)) {
        sprintf(fail_msg, "%s", "未获取到data字段!");
        goto fail;
    }

    const char* str = json_object_get_string_member(obj, data_key);
    vvd->data = strdup(str);

    g_object_unref(parser);
    return TRUE;
fail:
    vvd->fail_msg = strdup(fail_msg);
    g_object_unref(parser);
    return FALSE;
}

